package com.tianji.learning.service.impl;

import cn.hutool.core.bean.BeanUtil;
import com.tianji.api.client.course.CourseClient;
import com.tianji.api.dto.course.CourseFullInfoDTO;
import com.tianji.api.dto.leanring.LearningLessonDTO;
import com.tianji.api.dto.leanring.LearningRecordDTO;
import com.tianji.common.exceptions.BadRequestException;
import com.tianji.common.utils.BeanUtils;
import com.tianji.common.utils.ObjectUtils;
import com.tianji.common.utils.UserContext;
import com.tianji.learning.domain.dto.LearningRecordFormDTO;
import com.tianji.learning.domain.po.LearningLesson;
import com.tianji.learning.domain.po.LearningRecord;
import com.tianji.learning.enums.LessonStatus;
import com.tianji.learning.enums.SectionType;
import com.tianji.learning.mapper.LearningRecordMapper;
import com.tianji.learning.service.ILearningLessonService;
import com.tianji.learning.service.ILearningRecordService;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.tianji.learning.utils.LearningRecordDelayTaskHandler;
import lombok.RequiredArgsConstructor;
import org.springframework.context.annotation.Bean;
import org.springframework.stereotype.Service;

import java.util.List;

/**
 * <p>
 * 学习记录表 服务实现类
 * </p>
 *
 * @author ffk
 * @since 2024-06-22
 */
@Service
@RequiredArgsConstructor
public class LearningRecordServiceImpl extends ServiceImpl<LearningRecordMapper, LearningRecord> implements ILearningRecordService {


    private final ILearningLessonService learningLessonService;
    private  final CourseClient courseClient;
    private final LearningRecordDelayTaskHandler taskHandler;

    /**
     * 查询当前用户指定课程的学习进度
     * @param courseId 课程id
     * @return 课表信息、学习记录及进度信息
     */
    @Override
    public LearningLessonDTO queryLearningRecordByCourse(Long courseId) {

        //查询课程信息
         LearningLesson lesson = learningLessonService
                .lambdaQuery()
                .eq(LearningLesson::getUserId, UserContext.getUser())
                .eq(LearningLesson::getCourseId, courseId).one();

         //查询该课程的学习记录
        List<LearningRecord> lessonRecords = lambdaQuery()
                .eq(LearningRecord::getLessonId, lesson.getId())
                .list();
        List<LearningRecordDTO> learningRecordDTOS = BeanUtils.copyToList(lessonRecords, LearningRecordDTO.class);

        LearningLessonDTO lessonMsg = new LearningLessonDTO();
        lessonMsg.setId(lesson.getId());
        lessonMsg.setLatestSectionId(lesson.getLatestSectionId());
        lessonMsg.setRecords(learningRecordDTOS);

        return lessonMsg;
    }


    /**
     * 提交学习记录
     * @param recordDtoMsg
     */
    @Override
    public void addLessonRecords(LearningRecordFormDTO recordDtoMsg) {

        //处理学习记录,返回是否是第一次完成这一小节的学习，要去更新课程表用
      boolean finished=  recordDtoMsg.getSectionType()== SectionType.EXAM?addExamRecord(UserContext.getUser(),recordDtoMsg):addVideoRecord(UserContext.getUser(),recordDtoMsg);

      if(!finished || recordDtoMsg.getDuration()==-1){
          // 高并发优化，没有新学完的小节，无需更新课表中的学习进度
          return;
      }

      //先看课程存不存在
         Long lessonId = recordDtoMsg.getLessonId();
        LearningLesson theLesson = learningLessonService.lambdaQuery().eq(LearningLesson::getId, lessonId).one();
        if(ObjectUtils.isEmpty(theLesson)){
            throw new BadRequestException("该课程不存在,提交学习记录更新不了课程表");
        }

        //学完了一个小节，看有没有学完一门课程,那要得到该课程章节总数
        boolean flag=false;

            CourseFullInfoDTO courseInfo = courseClient.getCourseInfoById(theLesson.getId(), false, false);
            if(ObjectUtils.isEmpty(courseInfo)){
                throw new BadRequestException("该课程具体信息不存在,查不了课程的总章节数");
            }
            Integer sectionNum = courseInfo.getSectionNum();
            int learnedSections = theLesson.getLearnedSections()+ 1;
             flag=  learnedSections >= sectionNum;


         boolean updateResult = learningLessonService.lambdaUpdate()
                .set(LearningLesson::getLatestSectionId, recordDtoMsg.getSectionId())
                .set(LearningLesson::getLatestLearnTime, recordDtoMsg.getCommitTime())
                .setSql(finished, "learned_sections = learned_sections + 1")
                .set(theLesson.getStatus() == LessonStatus.NOT_BEGIN, LearningLesson::getStatus, LessonStatus.LEARNING.getValue())
                .set(flag, LearningLesson::getStatus, LessonStatus.FINISHED.getValue())
                .eq(LearningLesson::getId, theLesson.getId())
                .update();

         if(!updateResult){
             throw new BadRequestException("修改课程表失败");
         }

    }

    private boolean addExamRecord(Long Id, LearningRecordFormDTO recordDtoMsg) {

         LearningRecord learningRecord = BeanUtils.copyBean(recordDtoMsg, LearningRecord.class);
            learningRecord.setFinished(true);
            learningRecord.setFinishTime(recordDtoMsg.getCommitTime());
            learningRecord.setUserId(Id);

         boolean saveFlag = save(learningRecord);
        if(!saveFlag){
            throw new BadRequestException("保存考试记录失败");
        }
        return true;
    }

    private boolean addVideoRecord(Long userId, LearningRecordFormDTO recordDtoMsg) {
        //从redis查询旧的数据
         LearningRecord oldRecord = taskHandler.readLearningRecordFromCache(recordDtoMsg.getLessonId(), recordDtoMsg.getSectionId());
        if(ObjectUtils.isEmpty(oldRecord)){
         //redis没有,查数据库
            oldRecord = lambdaQuery().eq(LearningRecord::getSectionId, recordDtoMsg.getSectionId())
                    .eq(LearningRecord::getLessonId, recordDtoMsg.getLessonId())
                    .one();
            if(ObjectUtils.isEmpty(oldRecord)){
                //数据库没有
                oldRecord=null;
            }else{
                //数据库存在，存redis
                taskHandler.writeLearningRecordToCache(oldRecord);
            }

        }





         if(ObjectUtils.isEmpty(oldRecord)){
             //新增
            LearningRecord newRecord = BeanUtils.copyBean(recordDtoMsg, LearningRecord.class);
             newRecord.setUserId(userId);
              boolean flag = save(newRecord);
              if(!flag){
                  throw new BadRequestException("保存视频记录失败");
              }
             return false;
         }

        //是否第一次完成
         boolean isFirstFinished =  !oldRecord.getFinished() && recordDtoMsg.getMoment()*2 >= recordDtoMsg.getDuration();
        //否，存redis
        if(!isFirstFinished){
             LearningRecord learningRecord = new LearningRecord();
            learningRecord.setLessonId(recordDtoMsg.getLessonId());
            learningRecord.setSectionId(recordDtoMsg.getSectionId());
            learningRecord.setId(oldRecord.getId());
            learningRecord.setMoment(recordDtoMsg.getMoment());
            learningRecord.setFinished(oldRecord.getFinished());
            //定时任务
            taskHandler.addLearningRecordDelayCheckTask(learningRecord);
            recordDtoMsg.setDuration(-1);
            return false;
        }

        //是第一次学完，更新，清楚redis

         boolean updateFlag = lambdaUpdate()
                .set(LearningRecord::getMoment, recordDtoMsg.getMoment())
                .set(LearningRecord::getFinishTime, recordDtoMsg.getCommitTime())
                .set(LearningRecord::getFinished, true)
                .eq(LearningRecord::getId, oldRecord.getId())
                .update();

         if(!updateFlag){
             throw new BadRequestException("更新视频记录失败");
         }

        taskHandler.cleanLearningRecordCache(recordDtoMsg.getLessonId(),recordDtoMsg.getSectionId());
        return true;
    }
}
